<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="rules"
    :label-width="labelWidth"
    :inline="inline"
    class="common-form"
    v-bind="$attrs"
  >
    <template
      v-for="(item, index) in items"
      :key="index"
    >
      <el-form-item
        :prop="item.prop"
        :label="item.label"
        :required="item.required"
        :hidden="item.hidden"
        :label-width="item.labelWidth || labelWidth"
      >
        <!-- 输入框 -->
        <el-input
          v-if="item.type === 'input'"
          v-model="formData[item.prop]"
          v-bind="item.props"
        />

        <!-- 选择器 -->
        <el-select
          v-else-if="item.type === 'select'"
          v-model="formData[item.prop]"
          v-bind="item.props"
        >
          <el-option
            v-for="opt in item.options || []"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>

        <!-- 日期选择器 -->
        <el-date-picker
          v-else-if="item.type === 'date'"
          v-model="formData[item.prop]"
          v-bind="item.props"
        />

        <!-- 自定义内容 -->
        <template v-else-if="item.type === 'slot' && item.slot">
          <slot
            :name="item.slot"
            :formData="formData"
          />
        </template>
      </el-form-item>
    </template>

    <!-- 操作按钮 -->
    <el-form-item
      v-if="showActions"
      class="form-actions"
    >
      <slot name="actions">
        <el-button
          type="primary"
          @click="handleSubmit"
          >提交</el-button
        >
        <el-button @click="handleReset">重置</el-button>
      </slot>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
  import { defineProps, defineEmits, ref, reactive, watch, onMounted } from 'vue'
  import type { ElForm, FormRules } from 'element-plus'

  // 表单项配置类型
  export interface FormItem {
    prop: string
    label: string
    type: 'input' | 'select' | 'date' | 'slot'
    required?: boolean
    hidden?: boolean
    labelWidth?: string
    options?: { label: string; value: any }[] // 选择器选项
    props?: Record<string, any> // 组件属性
    slot?: string // 自定义插槽名
  }

  // 定义泛型 props
  const props = defineProps<{
    // 表单初始数据
    initialData: Record<string, any>
    // 表单项配置
    items: FormItem[]
    // 验证规则
    rules?: FormRules
    // 标签宽度
    labelWidth?: string
    // 是否为行内表单
    inline?: boolean
    // 是否显示操作按钮
    showActions?: boolean
  }>()

  const emit = defineEmits<{
    (e: 'submit', data: Record<string, any>): void
    (e: 'reset'): void
  }>()

  // 表单引用
  const formRef = ref<InstanceType<typeof ElForm>>()

  // 表单数据
  const formData = reactive<Record<string, any>>({})

  // 初始化表单数据
  const initFormData = () => {
    Object.assign(formData, props.initialData)
  }

  // 监听初始数据变化
  watch(
    () => props.initialData,
    newData => {
      Object.assign(formData, newData)
    },
    { deep: true },
  )

  // 提交表单
  const handleSubmit = async () => {
    if (!formRef.value) return
    try {
      await formRef.value.validate()
      emit('submit', { ...formData })
    } catch (error) {
      console.error('表单验证失败:', error)
    }
  }

  // 重置表单
  const handleReset = () => {
    formRef.value?.resetFields()
    emit('reset')
  }

  // 暴露表单方法
  defineExpose({
    validate: () => formRef.value?.validate(),
    resetFields: handleReset,
    getFormData: () => ({ ...formData }),
    setFormData: (data: Record<string, any>) => Object.assign(formData, data),
  })

  // 初始化
  onMounted(() => {
    initFormData()
  })
</script>

<style scoped>
  .common-form {
    width: 100%;
  }

  .form-actions {
    margin-top: 20px;
    display: flex;
    gap: 12px;
  }
</style>
